package net.lovesrc.allin.biz.stl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.zhouzhou.fastjava.BizException;
import com.zhouzhou.fastjava.http.MyHttpRequest;
import com.zhouzhou.fastjava.http.Requests;
import com.zhouzhou.fastjava.util.BigDecimalKit;
import com.zhouzhou.fastjava.util.MoneyKit;
import com.zhouzhou.fastjava.util.StringKit;
import com.zhouzhou.fastjava.util.ThreadKit;
import net.lovesrc.allin.biz.FileService;
import net.lovesrc.allin.biz.NotificationService;
import net.lovesrc.allin.biz.jietu.JieTuOuterContext;
import net.lovesrc.allin.biz.jietu.JieTuService;
import net.lovesrc.allin.biz.ocr.OcrService;
import net.lovesrc.allin.biz.pay.PayAccount;
import net.lovesrc.allin.biz.pay.PayService;
import net.lovesrc.allin.biz.user.UserService;
import net.lovesrc.allin.jobs.backup.StlAutoNewSellJob;
import net.lovesrc.allin.utils.MyRandomUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


@Service
public class StlService extends BaseStlService {

    @Autowired
    private PayService payService;

    /**
     * 交易的STL，折算
     */
    private static final double JY_RATE = 1.3;

    /**
     * 交易获取的额度比例
     */
    private static final double JY_LIMIT_GET_RATE = 1.6;

    @Autowired
    private JieTuService jieTuService;

    @Autowired
    private FileService fileService;

    @Autowired
    private OcrService ocrService;

    public StlUser getUserInfo(String mobile) {
        JSONObject resJson = this.post(mobile, "http://app.zaizhuji.cn/app/member/user.php?act=index");
        String html = resJson.getString("content");
        Document doc = Jsoup.parse(html);
        Elements moneyItems = doc.select("ul.userMoney > li");
        BigDecimal availableSellQty;
        try {
            availableSellQty = BigDecimal.valueOf(Double.valueOf(StringKit.extract(html, "可售额度：([0-9\\.]+)")));
        } catch (Exception e) {
            logger.error("获取可售余额异常, Mobile: {}", mobile, e);
            availableSellQty = BigDecimal.valueOf(-1024);
        }
        StlUser stlUser = StlUser.builder()
                .mobile(mobile)
                .availableSellQty(availableSellQty)
                .stlQty(BigDecimal.valueOf(Double.valueOf(moneyItems.get(0).selectFirst("p.value").text())))
                .stzQty(BigDecimal.valueOf(Double.valueOf(moneyItems.get(1).selectFirst("p.value").text())))
                .build();
        jdbcTemplate.update("update t_stl_account set maxSellQty = ?, availableSellQty = ?, stlQty = ?, stzQty = ? where mobile = ?",
                Math.min(
                        stlUser.getStlQty().intValue(),
                        stlUser.getAvailableSellQty().intValue()
                ),
                stlUser.getAvailableSellQty(),
                stlUser.getStlQty(),
                stlUser.getStzQty(),
                mobile
        );
        return this.buyKj(mobile, stlUser);
    }

    public void profits(int size) {
        List<JSONObject> rows = queryForRows(jdbcTemplate, "select mobile from t_stl_account " +
                        " where worked = 1 and stzQty >= 0 " +
                        " and profitTime < date(now()) " +
                        " and nextProfitTime > date(now()) and nextProfitTime <= now() " +
                        " order by nextProfitTime limit ?",
                size
        );
        for (JSONObject row : rows) {
            String mobile = row.getString("mobile");
            try {
                profit(mobile);
            } catch (BizException e) {
                if (e.getMessage().contains("无登录态")) {
                    // ignore
                    notificationService.syncEmail(NotificationService.LZQ_EMAIL, mobile + " -> 无登录态");
                } else {
                    throw e;
                }
            }
        }
    }

    public void profit(String mobile) {
        JSONObject resJson = this.postDong(mobile, "yjsb");
        jdbcTemplate.update("update t_stl_account set profitTime = ?, profitResText = ? where mobile = ?",
                new Date(),
                resJson.toJSONString(),
                mobile
        );
        // 转入矿池
        this.zrkc(mobile);
        this.signIn(mobile);
        this.getUserInfo(mobile);
    }

    private void zrkc(String mobile) {
        JSONObject resJson = this.postDong(mobile, "zrkc");
        int kjStl = resJson.getBigDecimal("kj_stl").intValue();
        if (kjStl >= 10) {
            int num = kjStl - (kjStl % 10);
            JSONObject zrkcUpResJson = this.postDong(mobile, "zrkc_up",
                    new JSONObject()
                            .fluentPut("num", num)
                            .fluentPut("type", 1)
            );
            try {
                checkResJson(zrkcUpResJson);
            } catch (BizException e) {
                if (e.getMessage().contains("矿机STL不足")) {
                    // ignore
                } else {
                    throw e;
                }
            }
        }
    }

    public void signIn(String mobile) {
        JSONObject row = queryForRow(jdbcTemplate, "select * from t_stl_account where mobile = ?", mobile);
        Date signInTime = row.getDate("signInTime");
        if (signInTime != null && signInTime.after(DateUtils.truncate(new Date(), Calendar.DAY_OF_MONTH))) {
            return;
        }
        JSONObject resJson = this.postDong(mobile, "qiandao");
        jdbcTemplate.update("update t_stl_account set signInTime = ?, signInResText = ? where mobile = ?",
                new Date(),
                resJson.toJSONString(),
                mobile
        );
    }

    private void readNotice(String mobile) {
        String aid = redisTemplate.opsForValue().get("STL_AID");
        if (StringUtils.isBlank(aid)) {
            JSONObject resJson = this.post(mobile, "http://app.zaizhuji.cn/app/index.php?act=street");
            checkResJson(resJson);
            String html = resJson.getString("content");
            Document doc = Jsoup.parse(html);
            Element popup = doc.selectFirst("#popups-notice");
            aid = popup.attr("aid");
            redisTemplate.opsForValue().set("STL_AID", aid, 5, TimeUnit.MINUTES);
        }
        if (!redisTemplate.hasKey("STL-NOTICE: " + mobile + aid)) {
            this.post(mobile, "http://app.zaizhuji.cn/app/index.php?act=help",
                    new JSONObject()
                            .fluentPut("article_id", aid)
            );
            redisTemplate.opsForValue().set("STL-NOTICE: " + mobile + aid, Boolean.TRUE.toString(), 3, TimeUnit.DAYS);
        }
    }

    /**
     * mobile zh name 肯定都不为空
     */
    private void doSetAlipay(String mobile, String zh, String name, String imgUri) {
        JSONObject row = queryForRow(jdbcTemplate, "select * from t_stl_account where mobile = ? and isMyAccount = 0", mobile);
        if (row == null) {
            return;
        }
        String alipay = row.getString("alipay");
        if (zh.equalsIgnoreCase(alipay)) {
            return;
        }
        JSONObject resJson = this.postDong(mobile, "act_bdzfb",
                new JSONObject()
                        .fluentPut("zh", zh)
                        .fluentPut("name", name)
                        .fluentPut("img", imgUri)
        );
        checkResJson(resJson);
        JSONObject userInfoJson = this.postDong(mobile, "getUserInfo");
        if (!Objects.equals(zh, userInfoJson.getString("zfb"))) {
            throw BizException.messageOf("支付宝未修改成功");
        }
        if (StringUtils.isNotBlank(userInfoJson.getString("wx"))) {
            execute(() -> this.clearWx(mobile));
        }
        jdbcTemplate.update("update t_stl_account set alipay = ? where mobile = ?", zh, mobile);
    }

    public void resetAlipay(String mobile) {
        JSONObject row = queryForRow(jdbcTemplate, "select * from t_stl_account where mobile = ? and isMyAccount = 0", mobile);
        if (row == null) {
            return;
        }
        this.doSetAlipay(mobile, mobile, row.getString("realName"), StringUtils.EMPTY);
    }

    private void clearWx(String mobile) {
        this.postDong(mobile, "act_bdwx",
                new JSONObject()
                        .fluentPut("zh", StringUtils.EMPTY)
                        .fluentPut("name", StringUtils.EMPTY)
        );
    }

    public List<StlOrder> getBuyOrders(String mobile) {
        return this.getOrders(mobile, 1);
    }

    public List<StlOrder> getSellOrders(String mobile) {
        return this.getOrders(mobile, 2);
    }

    private List<StlOrder> getOrders(String mobile, int zt) {
        JSONObject resJson = this.post(mobile, "http://app.zaizhuji.cn/app/member/user.php?act=wdjy&zt=" + zt + "&page=1");
        checkResJson(resJson);
        String html = resJson.getString("content");
        if (html.contains("暂无记录")) {
            return Lists.newArrayList();
        }
        Document root = Jsoup.parse(html);
        Elements items = root.select("li.item");
        List<StlOrder> orders = Lists.newArrayList();
        // 等待中 买家已付款 确认完成
        for (Element item : items) {
            StlOrder order = StlOrder.builder()
                    .jyId(item.attr("jy_id"))
                    .amount(BigDecimalKit.of(StringKit.extract(item.selectFirst("span.price").text(), "¥(.*)")))
                    .qty(Integer.valueOf(StringKit.extract(item.selectFirst(".counts").text(), "数量：(\\d+) STL")))
                    .jyStatus(item.selectFirst("span.status").text())
                    .build();
            orders.add(order);
        }
        return orders;
    }

    /**
     * 购买矿机
     */
    public StlUser buyKj(String mobile, StlUser stlUser) {

        int stzQty = stlUser.getStzQty().intValue();
        boolean hasBuyKj = false;
        List<JSONObject> rows = queryForRows(jdbcTemplate, "select * from t_stl_kj where mobile = ?", mobile);
        for (StlKjKind kjKind : StlKjKind.values()) {
            long qty = rows.stream()
                    .filter(row -> isWorkKj(row) && row.getString("name").contains(kjKind.getName()))
                    .count();
            for (int i = 0; i < kjKind.getMaxQty() - qty; i++) {
                if (stzQty >= kjKind.getPrice()) {
                    hasBuyKj = true;
                    doPay2(mobile, kjKind.getId());
                    stzQty = stzQty - kjKind.getPrice();
                }
            }
        }
        if (hasBuyKj || isMyMobile(mobile)) {
            this.getMyKjs(mobile);
        }
        if (hasBuyKj) {
            return this.getUserInfo(mobile);
        }
        return stlUser;
    }

    public void newSysJy(String owner) {
        checkOwner(owner);
        JSONObject sellerRow = queryForRow(jdbcTemplate, "select * from v_stl_account " +
                " where mobile not in (select mobile from v_stl_can_not_sell_now) " +
                " and mobile not in (select mobile from v_stl_can_not_buy_now) " +
                " and maxSellQty >= 10 * ?" +
                " order by maxSellQty desc limit 1", JY_RATE);
        if (sellerRow == null) {
            throw BizException.messageOf("无过渡小号");
        }
        String sellerMobile = sellerRow.getString("mobile");
        Integer maxJyQty = this.calcSellerMaxJyQty(this.getUserInfo(sellerMobile));
        String buyerMobile = this.newSysJyBuyer(maxJyQty);
        this.newJy(owner, "4NextDaySell", buyerMobile, sellerMobile);
    }

    public synchronized void newJy(String owner, String type, String buyerMobile, String sellerMobile) {

        checkOwner(owner);
        checkIsMobile(buyerMobile);
        checkIsMobile(sellerMobile);

        if (isNotJyTime()) {
            throw BizException.messageOf("当前不在交易时间内");
        }
        if (buyerMobile.equals(sellerMobile)) {
            throw BizException.messageOf("卖出和买入的账号不能一致");
        }
        if (jdbcTemplate.queryForObject("select count(1) from v_stl_can_not_sell_now where mobile = ?", int.class, sellerMobile) > 0) {
            throw BizException.messageOf("{} 今日已有卖出订单，无法再卖出了", sellerMobile);
        }

        List<StlJy> buyJyList = getBuyJyList(sellerMobile);
        if (buyJyList == null || buyJyList.isEmpty()) {
            throw BizException.messageOf("无求购订单，建议暂时不要交易");
        }
        StlUser sellerStlUser = this.getUserInfo(sellerMobile);
        Integer jyQty = calcSellerMaxJyQty(sellerStlUser);

        String price = getPrice(buyerMobile);

        JSONObject resJson = this.postDong(buyerMobile, "wymr",
                new JSONObject()
                        .fluentPut("num", jyQty)
                        .fluentPut("price", price)
                        .fluentPut("yj", 1)
        );
        checkResJson(resJson);
        StlOrder order = this.getBuyOrders(buyerMobile).stream().findFirst().get();
        String jyId = order.getJyId();
        try {
            JSONObject newRow = new JSONObject()
                    .fluentPut("jyId", jyId)
                    .fluentPut("status", "New")
                    .fluentPut("buyerMobile", buyerMobile)
                    .fluentPut("qty", jyQty)
                    .fluentPut("amount", order.getAmount())
                    .fluentPut("jyStatus", order.getJyStatus())
                    .fluentPut("owner", owner)
                    .fluentPut("type", type)
                    .fluentPut("resError", resJson.getIntValue("error"))
                    .fluentPut("resText", resJson.toJSONString());
            insertRow(jdbcTemplate, "t_stl_jy", newRow);
            this.buyJy(jyId, sellerMobile);
        } catch (Exception e) {
            this.cancelJy(buyerMobile, jyId);
            throw e;
        }
    }

    public String getPrice(String mobile) {
        JSONObject jyResJson = this.postDong(mobile, "jy");
        checkResJson(jyResJson);
        return jyResJson.getString("max_price");
    }

    private Integer calcSellerMaxJyQty(StlUser stlUser) {
        return uniformQty(
                Math.min(
                        Double.valueOf(stlUser.getStlQty().doubleValue() / JY_RATE).intValue(),
                        Double.valueOf(stlUser.getAvailableSellQty().doubleValue() / JY_RATE).intValue()
                )
        );
    }

    private Integer uniformQty(double qty) {
        Integer maxJyQty = tryGetProperties(int.class, 80, "Stl_Max_Jy_Qty");
        if (qty > maxJyQty) {
            qty = maxJyQty;
        }
        Integer uniformQty;
        if (qty >= 80) {
            uniformQty = 80;
        } else if (qty >= 50) {
            uniformQty = 50;
        } else if (qty >= 30) {
            uniformQty = 30;
        } else if (qty >= 10) {
            uniformQty = 10;
        } else {
            throw BizException.messageOf("计算交易数据错误");
        }
        return uniformQty;
    }

    /**
     * New 新增交易
     * Waiting_Buyer_Pay 等待买家付款
     * Waiting_Seller_Confirm 等待卖家确认
     * Success 交易完成（成功）
     */
    /**
     * 卖家，买币
     */
    private void buyJy(String jyId, String sellerMobile) {

        JSONObject jyRow = queryForRow(jdbcTemplate, "select * from t_stl_jy where jyId = ?", jyId);
        String buyerMobile = jyRow.getString("buyerMobile");
        String status = jyRow.getString("status");
        if (StringKit.notEqualsIgnoreCase("New", status)) {
            throw BizException.messageOf("状态异常");
        }
        JSONObject resJson = this.postDong(sellerMobile, "jyjy",
                new JSONObject()
                        .fluentPut("jy_id", jyId)
                        .fluentPut("dxm", StringUtils.EMPTY)
        );
        try {
            checkResJson(resJson);
        } catch (BizException e) {
            String message = e.getMessage();
            if (message.contains("抢先一步")) {
                StlJyDetail jyDetail = this.getJyShowAsBuyer(buyerMobile, jyId);
                if (sellerMobile.equalsIgnoreCase(jyDetail.getSellerMobile())) {
                    // is okay
                } else {
                    throw e;
                }
            } else {
                throw e;
            }
        }
        jdbcTemplate.update("update t_stl_jy set status = 'Waiting_Buyer_Pay', sellerMobile = ? where jyId = ?", sellerMobile, jyId);
    }

    public void cancelJy(String mobile, String jyId) {
        JSONObject resJson = this.postDong(mobile, "qxjy",
                new JSONObject()
                        .fluentPut("jy_id", jyId)
        );
        checkResJson(resJson);
        jdbcTemplate.update("update t_stl_jy set status = 'Cancelled' where jyId = ?", jyId);
    }

    public File jieTu(Integer jyId, boolean refresh) {
        File imgFile = new File(JieTuService.JIE_TU_DIR, "stl-jy-" + jyId + ".png");
        if (!imgFile.exists() || refresh) {
            return newJieTu(jyId);
        }
        return imgFile;
    }

    private File newJieTu(Integer jyId) {
        File file = jieTuService.newJieTu("http://localhost:8080/jietu/stl/alipay?jyId=" + jyId, "stl-jy-" + jyId);
        try {
            FileUtils.copyFileToDirectory(file, JieTuService.JIE_TU_DIR);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return new File(JieTuService.JIE_TU_DIR, "stl-jy-" + jyId + ".png");
    }

    public void payJyWithAutoJieTu(Integer jyId) {
        try {
            File imgFile = this.jieTu(jyId, false);
            this.payJy(jyId, imgFile);
        } catch (JSONException e) {
            if (e.getMessage().contains("imagecreatefrompng()")) {
                notificationService.syncEmail("截图上传异常，正在重新生成截图");
                jieTu(jyId, true);
            } else {
                throw e;
            }
        }
    }

    /**
     * 买家，点已付款  zfjy 支付交易
     */
    public void payJy(Integer jyId, File payImg) {
        JSONObject jyRow = queryForRow(jdbcTemplate, "select * from t_stl_jy where jyId = ?", jyId);
        String buyerMobile = jyRow.getString("buyerMobile");
        String status = jyRow.getString("status");
        if (StringKit.notEqualsIgnoreCase("Waiting_Buyer_Pay", status)) {
            throw BizException.messageOf("状态异常");
        }
        if (!payImg.exists()) {
            throw BizException.messageOf("文件不存在");
        }
        String uri = this.uploadFile(buyerMobile, payImg);
        JSONObject resJson = this.postDong(buyerMobile, "zfjy",
                new JSONObject()
                        .fluentPut("jy_id", jyId)
                        .fluentPut("img", uri)
        );
        checkResJson(resJson);
        jdbcTemplate.update("update t_stl_jy set status = 'Waiting_Seller_Confirm', payImgUrl = ? where buyerMobile = ? and jyId = ?", uri, buyerMobile, jyId);
    }

    public void sendVerifyCode3(String mobile) {

        checkIsMobile(mobile);
        boolean isNotMyMobile = this.isNotMyMobile(mobile);
        if (isNotMyMobile) {
            getMobileVerifyCodeWrapper().getPhone(mobile);
        }
        try {
            JSONObject resJson = this.postDong(mobile, "getVerifyCode3");
            checkResJson(resJson);
        } catch (Exception e) {
            if (isNotMyMobile) {
                getMobileVerifyCodeWrapper().releasePhone(mobile);
            }
            throw e;
        }
    }

    /**
     * 卖家，收到钱，完成，确认交易
     */
    public synchronized void confirmJY(Integer jyId) {
        checkNotNull("jyId", jyId);
        JSONObject jyRow = queryForRow(jdbcTemplate, "select * from t_stl_jy where jyId = ?", jyId);
        String status = jyRow.getString("status");
        if (StringKit.notEqualsIgnoreCase("Waiting_Seller_Confirm", status)) {
            throw BizException.messageOf("状态异常");
        }
        String sellerMobile = jyRow.getString("sellerMobile");
        String buyerMobile = jyRow.getString("buyerMobile");
        doConfirmJy(sellerMobile, jyId);
        jdbcTemplate.update("update t_stl_jy set status = 'Success' where jyId = ?", jyId);
        safeRun(() -> {
            this.getUserInfo(sellerMobile);
            this.getUserInfo(buyerMobile);
        });
    }

    public synchronized void confirmSellJY(String owner, Integer jyId) {
        checkOwner(owner);
        checkNotNull("jyId", jyId);
        JSONObject jyRow = queryForRow(jdbcTemplate, "select * from t_stl_sell where jyId = ?", jyId);
        String status = jyRow.getString("status");
        if (StringKit.notEqualsIgnoreCase("Waiting_Seller_Confirm", status)) {
            throw BizException.messageOf("状态异常");
        }
        String mobile = jyRow.getString("mobile");
        doConfirmJy(mobile, jyId);
        jdbcTemplate.update("update t_stl_sell set confirmBy = ?, confirmTime = ? where jyId = ?", owner, new Date(), jyId);
        this.doSyncSellJyStatus(jyId);
        this.resetAlipay(mobile);
        safeRun(() -> this.getUserInfo(mobile));
        //safeRun(() -> this.autoSysJy4Sell(UserService.SYSTEM));
    }

    public void syncSellJyStatus(boolean notice) {
        List<JSONObject> rows = queryForRows(jdbcTemplate, "select * from t_stl_sell where status in ('Waiting_Buyer_Pay')");
        for (JSONObject row : rows) {
            this.doSyncSellJyStatus(row.getInteger("jyId"), notice);
        }
    }

    private void doSyncSellJyStatus(Integer jyId) {
        this.doSyncSellJyStatus(jyId, false);
    }

    private void doSyncSellJyStatus(Integer jyId, boolean notice) {
        checkNotNull("jyId", jyId);
        JSONObject jyRow = queryForRow(jdbcTemplate, "select * from t_stl_sell where jyId = ?", jyId);
        String mobile = jyRow.getString("mobile");
        String owner = jyRow.getString("owner");
        StlJyDetail jyDetail = this.getJyShowAsSeller(mobile, jyId);
        String status = jyRow.getString("status");
        String newStatus = status;
        String jyStatus = jyDetail.getStatus();

        JSONObject sets = new JSONObject()
                .fluentPut("jyStatus", jyDetail.getStatus())
                .fluentPut("jyTime", jyDetail.getTime())
                .fluentPut("jyPayImgUrl", jyDetail.getPayImgUrl())
                .fluentPut("jyQty", jyDetail.getQty())
                .fluentPut("jyAmount", jyDetail.getAmount())
                .fluentPut("buyerMobile", jyDetail.getBuyerMobile());

        if ("待付款".equalsIgnoreCase(jyStatus)) {
            newStatus = "Waiting_Buyer_Pay";
            if (StringKit.notEqualsIgnoreCase(status, newStatus)) {
                updateAlipayIfNecessary(owner, jyRow, jyDetail.getBuyerMobile());
            }
        } else if ("待确认".equalsIgnoreCase(jyStatus)) {
            newStatus = "Waiting_Seller_Confirm";
            if (StringKit.notEqualsIgnoreCase(status, newStatus)) {
                sets.fluentPut("payTime", new Date());
                if (notice) {
                    // 邮件通知
                    String text = String.format("STL, Alipay: %s, Success", jyRow.getString("alipayRealName"));
                    syncNotice(owner, text);
                }
            }
        } else if ("已完成".equalsIgnoreCase(jyStatus)) {
            newStatus = "Success";
            sets.fluentPut("successTime", new Date());
        }
        sets.fluentPut("status", newStatus);
        updateRow(jdbcTemplate, "t_stl_sell", sets, "jyId = ?", jyId);
    }

    // 如果一个人交易过了，尽量更新支付宝
    private void updateAlipayIfNecessary(String owner, JSONObject jyRow, String buyerMobile) {
        Integer jyId = jyRow.getInteger("jyId");
        String alipayMobile = jyRow.getString("alipayMobile");
        Long id = jyRow.getLong("id");
        String mobile = jyRow.getString("mobile");
        int otherJyQty = jdbcTemplate.queryForObject(
                "select count(1) from t_stl_sell where jyId <> ? and mobile <> ? and alipayMobile = ? and buyerMobile = ?", int.class,
                jyId, mobile, alipayMobile, buyerMobile
        );
        if (otherJyQty > 0) {
            List<String> ingAlipayMobiles = getIngAlipayMobiles();
            List<String> linkedAlipayMobiles = jdbcTemplate.queryForList("select distinct alipayMobile from t_stl_sell where buyerMobile = ?", String.class, buyerMobile);
            List<PayAccount> payAccounts = payService.getWorkedAlipays()
                    .stream()
                    .filter(r -> !linkedAlipayMobiles.contains(r.getMobile()) && !ingAlipayMobiles.contains(r.getMobile()))
                    .collect(Collectors.toList());
            String text;
            if (payAccounts.isEmpty()) {
                text = String.format("Alipay: %s, BuyerMobile: %s 已经交易过了，无可用其他支付宝替换，不做变更", alipayMobile, buyerMobile);
            } else {
                PayAccount payAccount = payAccounts.get(RandomUtils.nextInt(0, payAccounts.size()));
                this.forceSetSellNewAlipay(id, payAccount.getId());
                text = String.format("Alipay: %s, BuyerMobile: %s 已经交易过了，系统自动更新为：%s", alipayMobile, buyerMobile, payAccount.getRealName());
            }
            syncNotice(owner, text);
        }
    }

    private void doConfirmJy(String mobile, Integer jyId) {
        JSONObject resJson = this.postDong(mobile, "qrjy", new JSONObject().fluentPut("jy_id", jyId));
        try {
            checkResJson(resJson);
        } catch (BizException e) {
            if (e.getMessage().contains("该交易已经确认了")) {
                // ok
            } else {
                throw e;
            }
        }
    }

    /**
     * zt: 1 求购列表
     * zt: 3 出售列表
     */
    public List<StlJy> getBuyJyList(String mobile) {
        return this.getJyList(mobile, 1);
    }

    public List<StlJy> getIngJyList(String mobile) {
        return this.getJyList(mobile, 3);
    }

    /**
     * 数量从大到小
     */
    private List<StlJy> getJyList(String mobile, int zt) {
        JSONObject row = queryForRow(jdbcTemplate, "select * from t_stl_account where mobile = ?", mobile);
        if (row == null) {
            throw BizException.messageOf("{} 不存在或者未实名通过", mobile);
        }
        CookieStore cookieStore = Requests.toCookieStore(row.getString("cookies"));
        HttpClient httpClient = newHttpClientBuilder(cookieStore).build();
        JSONObject resJson = MyHttpRequest.post(httpClient, "http://app.zaizhuji.cn/app/index.php?act=jy_list")
                .param("mobile", StringUtils.EMPTY)
                .param("zt", zt)
                .param("page", "1")
                .executeUtilReturn200()
                .asJson();
        checkResJson(resJson);
        String html = resJson.getString("content");
        if (html.contains("暂无记录")) {
            return Lists.newArrayList();
        }
        Document root = Jsoup.parse(html);
        Elements items = root.select("li.item");
        if (items.size() == 0) {
            return Lists.newArrayList();
        }
        List<StlJy> result = Lists.newArrayList();
        for (Element item : items) {
            BigDecimal amount = MoneyKit.of(Double.valueOf(StringKit.extract(item.selectFirst(".hd .price").text(), "¥(.*)")));
            Integer qty = Integer.valueOf(StringKit.extract(item.selectFirst(".counts .c5").text(), "(\\d+) STL"));
            String price = StringKit.extract(item.selectFirst(".info").text(), "单价：\\s*([\\.0-9]+)\\s*数量");
            Element btn = item.selectFirst("p.counts a.btn");
            Integer jyId = Integer.valueOf(btn.attr("jy_id"));
            result.add(
                    StlJy.builder()
                            .jyId(jyId)
                            .amount(amount)
                            .qty(qty)
                            .price(price)
                            .build()
            );
        }
        return result.stream()
                .sorted(Comparator.comparing(StlJy::getJyId).reversed())
                .collect(Collectors.toList());
    }

    public void updateMobileStatus() {
        jdbcTemplate.update("update t_stl_account set mobileStatus = 'Unknown'");
        List<JSONObject> rows = queryForRows(jdbcTemplate, "select mobile from t_stl_account where worked = 1");
        for (JSONObject row : rows) {
            String mobile = row.getString("mobile");
            try {
                getMobileVerifyCodeWrapper().getPhone(mobile);
                getMobileVerifyCodeWrapper().releasePhone(mobile);
                jdbcTemplate.update("update t_stl_account set mobileStatus = 'can-get' where mobile = ?", mobile);
            } catch (Exception e) {
                jdbcTemplate.update("update t_stl_account set mobileStatus = 'can-not-get' where mobile = ?", mobile);
            }
        }
    }

    private synchronized String newSysJyBuyer(Integer maxJyQty) {
        // 如果交易大于等于50的，应找系统中未交易过的数据
        if (maxJyQty >= 50) {
            JSONObject row = queryForRow(jdbcTemplate, "select * from v_stl_account " +
                    " where mobile not in (select buyerMobile from t_stl_jy where buyerMobile is not null) " +
                    " and stlQty >= 150" +
                    " order by rand() desc" +
                    " limit 1");
            return row.getString("mobile");
        } else {
            List<String> latestBuyerMobiles = jdbcTemplate.queryForList("select buyerMobile from t_stl_jy order by jyId desc limit 5", String.class);
            List<Object> params = Lists.newArrayList(JY_RATE, JY_RATE);
            params.addAll(latestBuyerMobiles);
            JSONObject row = queryForRow(jdbcTemplate, "select * from v_stl_account " +
                    " where stlQty >= availableSellQty + (50 + 10) * ? " +
                    " and availableSellQtyNextDay < 50 * ? " +
                    " and mobile not in (select buyerMobile from t_stl_jy where status in ('Waiting_Buyer_Pay', 'Waiting_Seller_Confirm')) " +
                    " and mobile not in (" + StringUtils.repeat("?", ", ", latestBuyerMobiles.size()) + ") " +
                    " order by truncate(availableSellQtyNextDay, -1) desc, rand() asc " +
                    " limit 1", params.toArray(new Object[0]));
            return row.getString("mobile");
        }
    }

    private StlJyDetail getJyShowAsBuyer(String buyerMobile, String jyId) {
        JSONObject resJson = this.post(buyerMobile, "http://app.zaizhuji.cn/app/member/user.php?act=jyshow&jy_id=" + jyId);
        checkResJson(resJson);
        String content = resJson.getString("content");
        Document doc = Jsoup.parse(content);
        return StlJyDetail.builder()
                .sellerMobile(doc.select("div.myTradeInfo > span.text").eq(1).text())
                .status(doc.selectFirst("span#zt").text().trim())
                .build();
    }

    private StlJyDetail getJyShowAsSeller(String sellerMobile, Integer jyId) {
        JSONObject resJson = this.post(sellerMobile, "http://app.zaizhuji.cn/app/member/user.php?act=jyshow&jy_id=" + jyId);
        checkResJson(resJson);
        String content = resJson.getString("content");
        Document doc = Jsoup.parse(content);
        String buyerMobile = doc.select("div.myTradeInfo > span.text")
                .stream()
                .filter(r -> {
                    String text = r.text().trim();
                    return NumberUtils.isDigits(text) && text.length() == 11;
                })
                .findFirst()
                .get()
                .text()
                .trim();
        Elements items = doc.select("ul.myTradeList li.item");
        String time = items.stream()
                .filter(r -> r.text().contains("时间"))
                .findFirst()
                .get()
                .selectFirst("span.value")
                .text().trim();
        String qty = items.stream()
                .filter(r -> r.text().contains("数量"))
                .findFirst()
                .get()
                .selectFirst("span.value")
                .text().trim();
        String amountText = items.stream()
                .filter(r -> r.text().contains("总价"))
                .findFirst()
                .get()
                .selectFirst("span.value")
                .text().trim();
        String amount = StringKit.extract(amountText, "¥(.*)");
        String status = items.stream()
                .filter(r -> r.text().contains("状态"))
                .findFirst()
                .get()
                .selectFirst("span#zt")
                .text().trim();
        Element imgDom = doc.selectFirst("ul.myTradeList li.item span.voucher img");
        String payImgUrl = imgDom != null ? imgDom.attr("src") : null;
        return StlJyDetail.builder()
                .sellerMobile(sellerMobile)
                .buyerMobile(buyerMobile)
                .time(time)
                .qty(qty)
                .amount(amount)
                .status(status)
                .payImgUrl(payImgUrl)
                .build();
    }

    /**
     * 转给自己的交易
     */
    public void newToMyJyWithAutoSelectSeller(String owner, String buyerMobile) {
        checkOwner(owner);
        JSONObject sellerRow = queryForRow(jdbcTemplate, "select * from t_stl_account where maxSellQty >= 10 * ? and maxSellQty < 30 * ?" +
                " and mobile not in (select mobile from v_stl_can_not_sell_now) " +
                " and mobile not in (select mobile from v_stl_jy_ing_mobile) " +
                " and worked = 1 and isMyAccount = 0 " +
                " order by maxSellQty desc, rand() asc limit 1", JY_RATE, JY_RATE);
        if (sellerRow == null) {
            throw BizException.messageOf("无可用小号");
        }
        this.newJy(owner, "SelfJy", buyerMobile, sellerRow.getString("mobile"));
    }

    public void once() throws IOException {
        List<JSONObject> rows = queryForRows(jdbcTemplate, "select * from t_stl_account where stzQty < 0 and worked = -1 order by stlQty desc limit 2000");
        for (JSONObject row : rows) {
            String mobile = row.getString("mobile");
            try {
                getMobileVerifyCodeWrapper().getPhone(mobile);
                getMobileVerifyCodeWrapper().releasePhone(mobile);
                this.profit(mobile);
                jdbcTemplate.update("update t_stl_account set worked = 1 where mobile = ?", mobile);
            } catch (Exception e) {
                jdbcTemplate.update("update t_stl_account set worked = 2, mark = ? where mobile = ?", e.getMessage(), mobile);
                logger.error(e.getMessage());
            }
        }
    }

    public String setAndSavePayMethod(String mobile) {
        String payMethod = MyRandomUtils.randomPayMethod();
        jdbcTemplate.update("update t_stl_account set payMethod = ? where mobile = ?", payMethod, mobile);
        return payMethod;
    }

    public void makeSellJy(Long id) {
        JSONObject row = queryForRow(jdbcTemplate, "select * from t_stl_sell where id = ?", id);
        Integer rowJyId = row.getInteger("jyId");
        if (rowJyId != null) {
            throw BizException.messageOf("已卖出，无法再卖出");
        }
        String sellerMobile = row.getString("mobile");
        String status = row.getString("status");
        if (StringKit.notEqualsIgnoreCase(status, "New")) {
            throw BizException.messageOf("此账号不是等待卖出状态");
        }
        StlUser stlUser = this.getUserInfo(sellerMobile);
        Integer jyQty = calcSellerMaxJyQty(stlUser);
        Integer jyId = this.bidJy(sellerMobile, Lists.newArrayList(jyQty), false);
        if (jyId != null) {
            jdbcTemplate.update("update t_stl_sell set jyId = ?, buyTime = ? where id = ?", jyId, new Date(), id);
            this.doSyncSellJyStatus(jyId);
        }
    }

    public Integer bidJy(String sellerMobile, List<Integer> qtys, boolean notice) {
        String price = getPrice(sellerMobile);
        for (int i = 0; i < 50; i++) {
            List<StlJy> stlJyList = this.getBuyJyList(sellerMobile)
                    .stream()
                    .sorted((o1, o2) -> {
                        if (!o2.getQty().equals(o1.getQty())) {
                            return o2.getQty() - o1.getQty();
                        }
                        return o2.getJyId() - o1.getJyId();
                    })
                    .filter(r -> Double.valueOf(price).equals(Double.valueOf(r.getPrice())))
                    .collect(Collectors.toList());
            for (StlJy stlJy : stlJyList) {
                Integer jyId = stlJy.getJyId();
                if (qtys.contains(stlJy.getQty())) {
                    JSONObject resJson = this.postDong(sellerMobile, "jyjy",
                            new JSONObject()
                                    .fluentPut("jy_id", jyId)
                                    .fluentPut("dxm", StringUtils.EMPTY)
                    );
                    try {
                        checkResJson(resJson);
                        if (notice) {
                            notificationService.syncEmail(NotificationService.LZQ_EMAIL, "Bid JY Success, Mobile: " + sellerMobile + ", Qty: " + stlJy.getQty() + ", Amount: " + stlJy.getAmount());
                        }
                        return jyId;
                    } catch (Exception e) {
                        logger.error("Bid Jy Error", e);
                        notificationService.syncEmail(NotificationService.LZQ_EMAIL, "Bid JY Failure, Message: " + e.getMessage());
                        return null;
                    }
                }
            }
            ThreadKit.sleepSeconds(1);
        }
        notificationService.syncEmail(NotificationService.LZQ_EMAIL, "Bid JY 超时, Mobile: " + sellerMobile);
        return null;
    }

    public void cancelSell(Long id) {
        JSONObject row = queryForRow(jdbcTemplate, "select * from t_stl_sell where id = ?", id);
        String mobile = row.getString("mobile");
        this.resetAlipay(mobile);
        String status = row.getString("status");
        if (StringUtils.equalsIgnoreCase(status, "Success")) {
            return;
        }
        jdbcTemplate.update("update t_stl_sell set status = 'Cancelled' where id = ?", id);
    }

    public String newSell(String owner) {
        return newSell(owner, getNextPayAccount4Sell().getId());
    }

    private PayAccount getNextPayAccount4Sell() {
        List<String> ingAlipayMobiles = getIngAlipayMobiles();
        List<PayAccount> workedAlipays = payService.getWorkedAlipays();
        List<PayAccount> availablePayAccounts = workedAlipays
                .stream()
                .filter(r -> !ingAlipayMobiles.contains(r.getMobile()))
                .collect(Collectors.toList());

        String latestAlipayMobile = jdbcTemplate.queryForObject("select alipayMobile from t_stl_sell where forceAlipay = 0 order by insertTime desc limit 1", String.class);
        PayAccount latestPayAccount = workedAlipays.stream()
                .filter(r -> r.getMobile().equalsIgnoreCase(latestAlipayMobile))
                .findFirst()
                .orElse(null);
        if (latestPayAccount == null) {
            return availablePayAccounts.get(0);
        }
        PayAccount nextPayAccount = availablePayAccounts
                .stream()
                .filter(r -> r.getSort() > latestPayAccount.getSort())
                .findFirst()
                .orElse(null);
        if (nextPayAccount == null) {
            return availablePayAccounts.get(0);
        }
        return nextPayAccount;
    }

    private List<JSONObject> findCanSellAccounts() {
        return queryForRows(jdbcTemplate, "select * from t_stl_account "
                + " where worked = 1 and isMyAccount = 0"
                + " and mobile not in (select mobile from v_stl_can_not_sell_now)"
                + " and mobile not in (select mobile from v_stl_jy_ing_mobile)"
                + " and alipay = mobile"
                + " and maxSellQty >= 10 * ?"
                + " and availableSellQty < ? * ?"
                + " order by maxSellQty desc", JY_RATE, tryGetProperties(int.class, 10, "Stl_Max_Sell_Jy_Qty"), JY_RATE
        );
    }

    public synchronized String newSell(String owner, String alipayAccountId) {
        checkOwner(owner);
        if (isNotJyTime()) {
            throw BizException.messageOf("当前不是交易时间");
        }
        // 是否开启了系统自动
        boolean autoNewSellJobEnabled = tryGetProperties(boolean.class, false, "Job." + StlAutoNewSellJob.class.getSimpleName());
        if (StringKit.notEqualsIgnoreCase(UserService.SYSTEM, owner) && autoNewSellJobEnabled) {
            throw BizException.messageOf("当前为系统自动模式，不可手工操作");
        }
        Date lastSellDate = jdbcTemplate.queryForObject("select insertTime from t_stl_sell order by id desc limit 1", Date.class);
        if (new Date().getTime() - lastSellDate.getTime() <= 2 * DateUtils.MILLIS_PER_MINUTE) {
            throw BizException.messageOf("请至少间隔2分钟");
        }
        List<JSONObject> canSellAccounts = findCanSellAccounts();
        if (canSellAccounts.isEmpty()) {
            throw BizException.messageOf("卖出小号不足");
        }
        JSONObject firstCanSellAccount = canSellAccounts.get(0);
        String stlMobile = firstCanSellAccount.getString("mobile");
        PayAccount alipayAccount = this.setToMyAlipay(stlMobile, alipayAccountId);
        // insert row
        JSONObject newRow = new JSONObject()
                .fluentPut("mobile", stlMobile)
                .fluentPut("alipayMobile", alipayAccount.getMobile())
                .fluentPut("alipayRealName", alipayAccount.getRealName())
                .fluentPut("status", "New")
                .fluentPut("owner", owner);
        insertRow(jdbcTemplate, "t_stl_sell", newRow);
        try {
            Long id = jdbcTemplate.queryForObject("select id from t_stl_sell where mobile = ? and status = 'New' order by id desc limit 1", Long.class, stlMobile);
            this.makeSellJy(id);
        } catch (Exception e) {
            jdbcTemplate.update("update t_stl_account set worked = 0, mark = ? where mobile = ?", e.getMessage(), stlMobile);
            throw e;
        }
        return stlMobile;
    }

    private List<String> getIngAlipayMobiles() {
        return jdbcTemplate.queryForList("select alipayMobile from t_stl_sell where status in ('New', 'Waiting_Buyer_Pay', 'Waiting_Seller_Confirm')", String.class);
    }

    private PayAccount setToMyAlipay(String stlMobile, String alipayAccountId) {
        PayAccount payAccount = payService.getWorkedAlipays()
                .stream()
                .filter(r -> r.getId().equalsIgnoreCase(alipayAccountId))
                .findFirst()
                .get();
        String alipayMobile = payAccount.getMobile();
        String alipayRealName = payAccount.getRealName();
        // 进行中的，不能再进行了
        List<String> ingAlipayMobiles = getIngAlipayMobiles();
        if (ingAlipayMobiles.contains(alipayMobile)) {
            throw BizException.messageOf("{} 正在进行中", alipayMobile);
        }
        {
            List<JSONObject> rows = queryForRows(jdbcTemplate, "select * from t_stl_account where alipay = ? and isMyAccount = 0", alipayMobile);
            for (JSONObject row : rows) {
                this.resetAlipay(row.getString("mobile"));
            }
        }
        String uri = uploadFile(stlMobile, new File("D:/data/pay-qr/" + payAccount.getAlipayFilename()));
        this.doSetAlipay(stlMobile, alipayMobile, alipayRealName, uri);
        return payAccount;
    }

    public void forceSetSellNewAlipay(Long id, String alipayAccountId) {
        JSONObject sellRow = queryForRow(jdbcTemplate, "select * from t_stl_sell where id = ?", id);
        String mobile = sellRow.getString("mobile");
        PayAccount alipayAccount = this.setToMyAlipay(mobile, alipayAccountId);
        jdbcTemplate.update("update t_stl_sell set alipayMobile = ?, alipayRealName = ?, forceAlipay = 1 where id = ?", alipayAccount.getMobile(), alipayAccount.getRealName(), id);
    }

    public JieTuOuterContext createJieTuOuterContext(Integer jyId) {
        JSONObject jyRow = queryForRow(jdbcTemplate, "select * from t_stl_jy where jyId = ?", jyId);
        String buyerMobile = jyRow.getString("buyerMobile");
        String sellerMobile = jyRow.getString("sellerMobile");
        JSONObject buyer = queryForRow(jdbcTemplate, "select * from t_stl_account where mobile = ?", buyerMobile);
        JSONObject seller = queryForRow(jdbcTemplate, "select * from t_stl_account where mobile = ?", sellerMobile);

        String buyerPayMethod = buyer.getString("payMethod");
        if (StringUtils.isBlank(buyerPayMethod)) {
            buyerPayMethod = this.setAndSavePayMethod(buyerMobile);
        }
        return JieTuOuterContext.builder()
                .buyerMobile(buyerMobile)
                .buyerPayMethod(buyerPayMethod)
                .amount(jyRow.getBigDecimal("amount"))
                .sellerRealName(seller.getString("realName"))
                .build();
    }

    public synchronized void autoSysJy4Sell(String owner) {
        /*
        checkOwner(owner);
        List<JSONObject> canSellAccounts = findCanSellAccounts();
        if (canSellAccounts.size() >= 7) {
            return;
        }
        int maxSellQtyLine = Double.valueOf(30 * JY_RATE - 10 * JY_LIMIT_GET_RATE).intValue();
        List<String> buyerMobiles = jdbcTemplate.queryForList("select mobile from v_stl_account " +
                " where availableSellQty < 10 * ? and availableSellQty >= ?" +
                " and stlQty >= 30 * ?" +
                " and mobile not in (select mobile from v_stl_can_not_sell_now)" +
                " and mobile not in (select mobile from v_stl_jy_ing_mobile)" +
                " order by maxSellQty desc, stlQty desc limit 1", String.class, JY_RATE, maxSellQtyLine, JY_RATE);
        if (buyerMobiles.isEmpty()) {
            return;
        }
        String buyerMobile = buyerMobiles.get(0);

        List<String> sellerMobiles = jdbcTemplate.queryForList("select mobile from v_stl_account " +
                " where maxSellQty >= 10 * ? and maxSellQty < 30 * ?" +
                " and mobile not in (select mobile from v_stl_can_not_sell_now)" +
                " and mobile not in (select mobile from v_stl_jy_ing_mobile)" +
                " and mobile <> ? " +
                " order by maxSellQty asc, stlQty asc limit 1", String.class, JY_RATE, JY_RATE, buyerMobile);
        if (sellerMobiles.isEmpty()) {
            return;
        }
        String sellerMobile = sellerMobiles.get(0);
        this.newJy(owner, "4Sell", buyerMobile, sellerMobile);
        */
    }

    public synchronized void autoSysJy4SellTen(String owner) {
        /*
        checkOwner(owner);
        List<String> buyerMobiles = jdbcTemplate.queryForList("select mobile from v_stl_account " +
                " where availableSellQty < 10 * ? and availableSellQty >= 5 * ?" +
                " and stlQty >= 10 * ?" +
                " and mobile not in (select mobile from v_stl_can_not_sell_now)" +
                " and mobile not in (select mobile from v_stl_can_not_buy_now)" +
                " and mobile not in (select mobile from v_stl_jy_ing_mobile)" +
                " order by maxSellQty desc, stlQty desc limit 1", String.class, JY_RATE, JY_RATE, JY_RATE);
        if (buyerMobiles.isEmpty()) {
            return;
        }
        String buyerMobile = buyerMobiles.get(0);

        List<String> sellerMobiles = jdbcTemplate.queryForList("select mobile from v_stl_account " +
                " where maxSellQty >= 5 * ? and maxSellQty < 10 * ?" +
                " and mobile not in (select mobile from v_stl_can_not_sell_now)" +
                " and mobile not in (select mobile from v_stl_jy_ing_mobile)" +
                " and mobile <> ? " +
                " order by maxSellQty asc, stlQty asc limit 1", String.class, JY_RATE, JY_RATE, buyerMobile);
        if (sellerMobiles.isEmpty()) {
            return;
        }
        String sellerMobile = sellerMobiles.get(0);
        this.newJy(owner, "4SellTen", buyerMobile, sellerMobile);
        */
    }

    public boolean canAutoConfirmSellJy(Integer jyId) throws IOException {
        JSONObject sellRow = queryForRow(jdbcTemplate, "select * from t_stl_sell where jyId = ?", jyId);
        String jyPayImgUrl = sellRow.getString("jyPayImgUrl");
        File img = fileService.save(jyPayImgUrl);
        JSONObject resJson = ocrService.generalBasic(img);
        JSONArray words = resJson.getJSONArray("words_result");
        StringBuilder textsBuilder = new StringBuilder();
        for (int i = 0; i < words.size(); i++) {
            textsBuilder.append(words.getJSONObject(i).getString("words"));
        }
        String texts = textsBuilder.toString();

        String alipayOrderNoRegex = DateFormatUtils.format(new Date(), "yyyyMMdd") + "\\d{23}";
        Pattern alipayOrderNoPattern = Pattern.compile(alipayOrderNoRegex);

        List<String> jyAmounts = Lists.newArrayList();
        String jyAmount = sellRow.getString("jyAmount");
        jyAmounts.add(jyAmount);
        jyAmounts.add(String.valueOf(Double.valueOf(Double.valueOf(jyAmount) * 100).intValue()));
        jyAmounts.add(jyAmount.replace(".", ","));

        String alipayMobile = sellRow.getString("alipayMobile");
        PayAccount payAccount = payService.getWorkedAlipays()
                .stream()
                .filter(r -> r.getMobile().equalsIgnoreCase(alipayMobile))
                .findFirst()
                .get();
        if (StringUtils.containsIgnoreCase(texts, "stl")) {
            return false;
        }
        if ((texts.contains("收款") || texts.contains("转账") || texts.contains("交易成功") || alipayOrderNoPattern.matcher(texts).find())
                && StringUtils.containsAny(texts, jyAmounts.toArray(new String[0]))) {
            // 金额和姓名，都匹配得上
            if (StringUtils.containsIgnoreCase(texts, payAccount.getAlipayNickname()) || StringUtils.containsIgnoreCase(texts, payAccount.getRealName().substring(1))) {
                return true;
            }
        }
        return false;
    }

}
